﻿// ***********************************************************************
// Assembly         : Delta_util
// Author           : Juan Alberto Cerino Gomez
// Created          : 02-18-2013
//
// Last Modified By : Juan Alberto Cerino Gomez
// Last Modified On : 05-08-2013
// ***********************************************************************
// <copyright file="Comun.cs" company="Delta Bussines">
//     Copyright (c) 2013  Delta Bussines. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Security.Cryptography;
using Delta_util.Estaticos;
using System.Xml;
using System.Collections;
using System.Collections.Specialized;

namespace Delta_util.Clases
{
    /// <summary>
    /// Clase que se encarga de realizar operaciones usando reflexion a los objetos.
    /// </summary>
    public static class Comun
    {
        #region Datos para el acceso a la base de datos
        /// <summary>
        /// The bd
        /// </summary>
        public static string bd = null;
        /// <summary>
        /// The servidor
        /// </summary>
        public static string servidor = null;
        /// <summary>
        /// The usr
        /// </summary>
        public static string usr = null;
        /// <summary>
        /// The pass
        /// </summary>
        public static string pass = null;
        #endregion

        #region XML

        /// <summary>
        /// Se encarga de obtener los valores de un documento XML, este metodo es usado para manejar los datos dinamicos de las entidades.
        /// </summary>
        /// <param name="docXML">El documento XML que contiene los datos dinamicos.</param>
        /// <param name="campo">El nombre del campo del cual se quiere obtener el valor.</param>
        /// <param name="tipo">El nombre del tipo de dato del dato, nombre completo del tipo.</param>
        /// <param name="simpleNodo">Indica si contiene solo un nodo(true) o varios nodos(false).</param>
        /// <returns>Si se encuentra el dato, retorna el valor como Object, en caso contrario se devuelve NULL.</returns>
        public static object ObtenerValorXML(XmlDocument docXML, string campo, string tipo, bool simpleNodo = true)
        {
            XmlNode nodo = null;
            if (docXML != null)
            {
                if (simpleNodo)
                    nodo = docXML.HasChildNodes ? (docXML.ChildNodes[0].HasChildNodes ? docXML.ChildNodes[0].ChildNodes[0] : null) : null;
                else
                    nodo = docXML.SelectSingleNode("/root/dat[@id='" + campo + "']");
            }
            if (nodo != null && nodo.Attributes[campo] != null)
            {
                if (tipo.ToUpper() == typeof(DateTime).FullName.ToUpper())
                {

                    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
                    return (object)DateTime.Parse(nodo.Attributes[campo].Value);
                }
                else
                    return Convertir(nodo.Attributes[campo].Value, Type.GetType(tipo));
            }
            else
                return EjecutarMetodoObjGenerico(typeof(Comun), "obtenerValorDefaultTipo", Type.GetType(tipo), null);
        }
        #endregion

        #region REFLEJTION

        /// <summary>
        /// Este metodo se encarga de obtener el valor de un objeto, de acuerdo al nombre de la propiedad o campo, recuerde que al obtener el valor se valida el nivel de proteccion de la propiedad o campo.
        /// </summary>
        /// <param name="fuente">La clase que contiene la propiedad o campo del cual se va a obtener el valor.</param>
        /// <param name="nombre">Nombre de la propiedad o campo.</param>
        /// <returns>Si se encuentra la propiedad o campo, retorna el valor como Object, en caso contrario se devuelve NULL.</returns>
        public static object ObtenerDato(object fuente, string nombre)
        {

            PropertyInfo dprop = fuente.GetType().GetProperty(nombre);
            FieldInfo variable = fuente.GetType().GetField(nombre);

            if (dprop != null)
                return dprop.GetValue(fuente, null);
            else
                if (variable != null)
                    return variable.GetValue(fuente);
                else
                    return null;

        }
        /// <summary>
        /// Metodo generico que se encarga de obtener un atributo personalizado de una propiedad de una clase.
        /// </summary>
        /// <typeparam name="T">El tipo del atributo, debe heredar a System.Attribute.</typeparam>
        /// <param name="tipo">El tipo de dato de la entidad.</param>
        /// <param name="prop">Datos de la propiedad a la cual se quiere obtener el atributo.</param>
        /// <returns>Si se encuentra la propiedad o campo, retorna el valor como Object, en caso contrario se devuelve NULL.</returns>
        public static T ObtenerAtributoEntidad<T>(Type tipo, PropertyInfo prop) where T : System.Attribute
        {
            if (tipo == null || prop == null)
                return default(T);
            object[] atributos = null;
            atributos = prop.GetCustomAttributes(typeof(T), false);
            if (atributos != null && atributos.Length > 0)
                return (T)atributos[0];
            else
                return default(T);
        }

        /// <summary>
        /// Metodo generico que se encarga de obtener un atributo personalizado de una propiedad de una clase.
        /// </summary>
        /// <typeparam name="T">El tipo del atributo, debe heredar a System.Attribute.</typeparam>
        /// <param name="tipo">El tipo de dato de la entidad.</param>
        /// <param name="propiedad">Datos de la propiedad a la cual se quiere obtener el atributo.</param>
        /// <returns>Si se encuentra la propiedad o campo, retorna el valor como Object, en caso contrario se devuelve NULL.</returns>
        public static T ObtenerAtributoEntidad<T>(Type tipo, string propiedad = null) where T : System.Attribute
        {
            if (tipo == null)
                return default(T);
            object[] atributos = null;
            if (propiedad == null)
                atributos = tipo.GetCustomAttributes(typeof(T), false);
            else
            {
                PropertyInfo prop = tipo.GetProperty(propiedad);
                atributos = prop.GetCustomAttributes(typeof(T), false);
            }
            if (atributos != null && atributos.Length > 0)
                return (T)atributos[0];
            else
                return default(T);
        }

        /// <summary>
        /// Metodo que se encarga de ejecutar un metodo de un objeto, recuerde que el metodo debe ser publico para que pueda ser ejecutado.
        /// </summary>
        /// <param name="objeto">El objeto que contiene el metodo.</param>
        /// <param name="metodo">Nombre del metodo a ejecutar.</param>
        /// <param name="parametros">Arreglo con los parametros del metodo.</param>
        /// <returns>Si se encuentra la propiedad o campo, retorna el valor como Object, en caso contrario se devuelve NULL.</returns>
        public static object EjecutarMetodoObjGet(object objeto, string metodo, params object[] parametros)
        {

            MethodInfo propTipo = objeto.GetType().GetMethod(metodo);
            if (propTipo != null)
                return propTipo.Invoke(objeto, (parametros == null || parametros.Count() == 0) ? null : parametros);
            else
                return null;


        }

        /// <summary>
        /// Metodo que ejecuta un evento de un componente web.
        /// </summary>
        /// <param name="source">El componente que contiene el evento.</param>
        /// <param name="eventName">Nombre del evento a provocar.</param>
        /// <param name="parametros">Lista de parametros que se enviaran en el evento.</param>
        public static void ProvocarEvento(Control source, string eventName, params object[] parametros)
        {
            var eventInfo = source.GetType().GetEvent(eventName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            if (eventInfo == null)
                return;
            var eventDelegate = (MulticastDelegate)source.GetType().BaseType.GetField(eventName, BindingFlags.Public | BindingFlags.Instance).GetValue(source);
            if (eventDelegate != null)
            {
                foreach (var handler in eventDelegate.GetInvocationList())
                {
                    handler.Method.Invoke(handler.Target, parametros);
                }
            }
        }

        /// <summary>
        /// Metodo que ejecuta un evento de un objeto.
        /// </summary>
        /// <param name="objeto">El objeto que contiene el evento.</param>
        /// <param name="evento">Nombre del evento a provocar.</param>
        /// <param name="parametros">Lista de parametros a enviar al evento.</param>
        public static void EjecutarMetodoObj(object objeto, EventInfo evento, params object[] parametros)
        {
            if (evento == null)
                return;
            MethodInfo metodo = evento.GetRaiseMethod();
            if (metodo != null)
                metodo.Invoke(objeto, (parametros == null || parametros.Count() == 0) ? null : parametros);

        }

        /// <summary>
        /// Metodo que ejecuta un metodo de un objeto, este metodo no devuelve el resultado de la ejecución. 
        /// </summary>
        /// <param name="objeto">El objeto que contiene el metodo.</param>
        /// <param name="metodo">La información del metodo a ejecutar.</param>
        /// <param name="parametros">Lista de parametros a enviar al metodo.</param>
        public static void EjecutarMetodoObj(object objeto, MethodInfo metodo, params object[] parametros)
        {

            if (metodo != null)
                metodo.Invoke(objeto, (parametros == null || parametros.Count() == 0) ? null : parametros);

        }

        /// <summary>
        /// Metodo que ejecuta un metodo de un objeto, este metodo no devuelve el resultado de la ejecución. 
        /// </summary>
        /// <param name="objeto">El objeto que contiene el metodo.</param>
        /// <param name="metodo">Nombre del metodo a ejecutar.</param>
        /// <param name="parametros">Lista de parametros a enviar al metodo.</param>
        public static void EjecutarMetodoObj(object objeto, string metodo, params object[] parametros)
        {

            MethodInfo propTipo = objeto.GetType().GetMethod(metodo);
            if (propTipo != null)
                propTipo.Invoke(objeto, (parametros == null || parametros.Count() == 0) ? null : parametros);

        }

        /// <summary>
        /// Metodo que ejecuta un metodo generico y devuelve el valor de la ejecución.
        /// </summary>
        /// <param name="objeto">El objeto que contiene el metodo.</param>
        /// <param name="metodo">Nombre del metodo a ejecutar.</param>        
        /// <param name="tipo">El tipo de dato que se enviara al metodo generico.</param>
        /// <param name="parametros">Lista de parametros a enviar al metodo.</param>
        /// <returns>Si se encuentra el metodo, retorna el resultado como Object, en caso contrario se devuelve NULL.</returns>
        public static object EjecutarMetodoObjGenerico(object objeto, string metodo, Type tipo, params object[] parametros)
        {
            return EjecutarMetodoObjGenerico(objeto.GetType(), metodo, tipo, parametros);
        }
        /// <summary>
        /// Ejecutars the metodo obj generico.
        /// </summary>
        /// <param name="objeto">El objeto que contiene el metodo.</param>
        /// <param name="metodo">Nombre del metodo a ejecutar.</param>        
        /// <param name="tipo">El tipo de dato que se enviara al metodo generico.</param>
        /// <param name="parametros">Lista de parametros a enviar al metodo.</param>
        /// <returns>Si se encuentra el metodo, retorna el resultado como Object, en caso contrario se devuelve NULL.</returns>
        public static object EjecutarMetodoObjGenerico(Type objeto, string metodo, Type tipo, params object[] parametros)
        {

            MethodInfo propTipo = objeto.GetType().GetMethod(metodo);

            if (propTipo != null)
            {
                propTipo = propTipo.MakeGenericMethod(tipo);
                return propTipo.Invoke(objeto, (parametros == null || parametros.Count() == 0) ? null : parametros);
            }
            else
                return null;

        }
        /// <summary>
        /// Metodo que verifica si un objeto contiene una propiedad.
        /// </summary>
        /// <param name="objeto">El objeto donde se realiza la busqueda de la propiedad.</param>
        /// <param name="propiedad">Nombre de la propiedad a buscar.</param>
        /// <returns>Devuelve true si existe, en caso contrario devuelve false.</returns>
        public static bool ExistePropiedad(object objeto, string propiedad)
        {
            PropertyInfo propTipo = objeto.GetType().GetProperty(propiedad);
            return propTipo != null;
        }
        /// <summary>
        /// Se encarga de obtener el tipo de dato de una propiedad.
        /// </summary>
        /// <param name="objeto">El objeto que contiene la propiedad.</param>
        /// <param name="propiedad">El nombre de la propiedad a buscar.</param>
        /// <returns>Devuelve información del tipo de dato de la propiedad, si existe, en caso contrario devuelve NULL.</returns>
        public static Type ObtenerTipoPropiedad(object objeto, string propiedad)
        {

            PropertyInfo propTipo = objeto.GetType().GetProperty(propiedad);
            if (propTipo != null)
                return propTipo.PropertyType;
            else
                return null;

        }



        /// <summary>
        /// Metodo que se encarga de clonar una entidad.
        /// </summary>
        /// <param name="entidad">Entidad a clonar.</param>
        /// <returns>System.Object que contiene los datos clonados de la entidad.</returns>
        public static object ClonarEntidad(object entidad)
        {

            if (entidad == null)
                return null;

            var ninstancia = CrearInstancia(entidad.GetType());
            foreach (PropertyInfo llave in entidad.GetType().GetProperties())
            {
                FijarValorObjeto(ninstancia, llave.GetValue(entidad, null), llave.Name);
            }
            return ninstancia;
        }

        /// <summary>
        /// Metodo que se encarga de rellenar una entidad apartir de un diccionario de valores.
        /// </summary>
        /// <param name="valores">Diccionario con los valores de la entidad.</param>
        /// <param name="entidad">La entidad en la que se escribirán los datos.</param>
        public static void RellenarEntidad(IOrderedDictionary valores, object entidad)
        {
            if (valores == null || entidad == null)
                return;
            foreach (string llave in valores.Keys)
            {
                FijarValorObjeto(entidad, valores[llave], llave);
            }
        }

        /// <summary>
        /// Metodo que se encarga de rellenar una entidad apartir de un diccionario de valores.
        /// </summary>
        /// <param name="valores">Diccionario con los valores de la entidad.</param>
        /// <param name="entidad">La entidad en la que se escribirán los datos.</param>
        public static void RellenarEntidad(IDictionary<string, object> valores, object entidad)
        {
            if (valores == null || entidad == null)
                return;
            foreach (string llave in valores.Keys)
            {
                FijarValorObjeto(entidad, valores[llave], llave);
            }
        }

        /// <summary>
        /// Se encarga de rellenar una entidad apartir de otra entidad, descartando los valores nulos de la entidad origen.
        /// </summary>
        /// <param name="entidadOrigen">Entidad de la cual se tomarán los valores.</param>
        /// <param name="entidad">Entidad en la cual se escribirán los datos.</param>
        public static void RellenarEntidadSinNULL(object entidadOrigen, object entidad)
        {
            if (entidadOrigen == null || entidad == null)
                return;
            foreach (PropertyInfo llave in entidadOrigen.GetType().GetProperties())
            {
                object val = llave.GetValue(entidadOrigen, null);
                if (val != null)
                    FijarValorObjeto(entidad, val, llave.Name);
            }
        }

        /// <summary>
        /// Rellena una entidad apartir de un HashTable con los valores a insertar.
        /// </summary>
        /// <param name="valores">HashTable que contiene el nombre y valor de la propiedad.</param>
        /// <param name="entidad">Entidad en la cual se escribirán los datos.</param>
        public static void RellenarEntidad(Hashtable valores, object entidad)
        {
            if (valores == null || entidad == null)
                return;
            foreach (string llave in valores.Keys)
            {
                FijarValorObjeto(entidad, valores[llave], llave);
            }
        }
        /// <summary>
        /// Se encarga de obtener el valor de una propiedad, convirtiendo el valor al tipo especifíco.
        /// </summary>
        /// <typeparam name="T">Tipo de dato de la propiedad.</typeparam>
        /// <param name="objeto">El objeto en el cual se encuentra la propiedad.</param>
        /// <param name="propiedad">Nombre de la propiedad a buscar.</param>
        /// <returns>Valor convertido al tipo especificado.</returns>
        public static T ObtenerValorPropiedad<T>(object objeto, string propiedad)
        {

            PropertyInfo propTipo = objeto.GetType().GetProperty(propiedad);
            if (propTipo != null)
                return (T)propTipo.GetValue(objeto, null);
            else
                return default(T);

        }
        /// <summary>
        /// Se encarga de obtener el valor de una propiedad.
        /// </summary>
        /// <param name="objeto">El objeto en el cual se encuentra la propiedad.</param>
        /// <param name="propiedad">Nombre de la propiedad a buscar.</param>
        /// <returns>Si la propiedad existe, devuelve el valor representado como "Object", en caso contrario, devuelve un valor nulo.</returns>
        public static object ObtenerValorPropiedad(object objeto, string propiedad)
        {

            PropertyInfo propTipo = objeto.GetType().GetProperty(propiedad.Trim());
            if (propTipo != null)
                return propTipo.GetValue(objeto, null);
            else
                return null;

        }
        /// <summary>
        /// Metodo que obtiene los datos de un evento de un objeto.
        /// </summary>
        /// <param name="objeto">Objeto en el cual se va a realizar la busqueda del evento.</param>
        /// <param name="nombre">Nombre del evento a buscar.</param>
        /// <returns>Si el evento existe, retorna los datos del evento como "EventInfo", en caso contrario, devuelve un valor nulo.</returns>
        public static EventInfo ObtenerEvento(object objeto, string nombre)
        {

            EventInfo propTipo = objeto.GetType().GetEvent(nombre);
            if (propTipo != null)
                return propTipo;
            else
                return null;

        }


        #endregion

        /// <summary>
        /// Metodo que valida si una propiedad existe en una lista de configuración dinámica de campos.
        /// </summary>
        /// <param name="propiedad">Nombre de la propiedad a buscar.</param>
        /// <param name="configUsers">Lista de configuración dinámica de un tipo de dato.</param>
        /// <returns><c>true</c>  si existe la propiedad, <c>false</c> en caso contrario.</returns>
        public static bool PropiedadDinamica(string propiedad, List<dynamic> configUsers)
        {
            if (configUsers == null)
                return false;
            foreach (dynamic dato in configUsers)
            {
                if (dato.nombre == propiedad)
                    return true;
            }
            return false;
        }
        /// <summary>
        /// Metodo que devuevle la representación MD5 de una cadena de caracteres.
        /// </summary>
        /// <param name="cadena">Cadena que se representará en MD5.</param>
        /// <returns>Representación en MD5 de la cadena.</returns>
        public static string getMD5(string cadena)
        {
            return GetMd5Hash(MD5.Create(), cadena);
        }

        /// <summary>
        /// Metodo que se encarga de generar la representación MD5 de una cadena de caracteres.
        /// </summary>
        /// <param name="md5Hash">El hash MD5 a usar para representar la cadena.</param>
        /// <param name="input">Cadena que se representará en MD5.</param>
        /// <returns>Representación en MD5 de la cadena</returns>
        private static string GetMd5Hash(MD5 md5Hash, string input)
        {


            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

            StringBuilder sBuilder = new StringBuilder();

            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            return sBuilder.ToString();
        }
        /// <summary>
        /// Metodo que se encarga de asignar valor a una propiedad de un objeto.
        /// </summary>
        /// <param name="dato">El objeto en el cual se va a escribir el dato.</param>
        /// <param name="valor">El valor a escribir.</param>
        /// <param name="prop_">Nombre de la propiedad en la cual se escribirá el valor.</param>
        /// <param name="convertirATipo">Indica si el valor se debe convertir al tipo de propiedad (true) o asignarlo tal y como lo envio el usuario(false).</param>
        /// <returns>Devuelve un valor logico que indica si se logro asingar el valor a la propiedad</returns>
        public static bool FijarValorObjeto(object dato, object valor, string prop_, bool convertirATipo = true)
        {
            try
            {
                PropertyInfo prop = dato.GetType().GetProperty(prop_);
                if (prop != null)
                {

                    object valorProp = valor;
                    if (convertirATipo)
                        valorProp = Comun.Convertir(valor, prop.PropertyType, Comun.ObtenerDefaultTipo(prop.PropertyType));
                    prop.SetValue(dato, valorProp, null);
                    return true;
                }
                else
                    return false;
            }
            catch { return false; }
        }
        /// <summary>
        /// Metodo que se encarga de escribir un valor en la sesión actual.
        /// </summary>
        /// <param name="pagina">Pagina web que contiene la sesión.</param>
        /// <param name="clave">Nombre de la clave en la cual se guarda el valor.</param>
        /// <param name="valor">El valor a guardar en la sesión.</param>
        public static void FijarValorSesion(Page pagina, string clave, object valor)
        {
            pagina.Session[clave] = valor;
        }


        /// <summary>
        /// Metodo que se encarga de obtener un dato de la sesión.
        /// </summary>
        /// <param name="pagina">Página que contiene la sesión.</param>
        /// <param name="clave">Clave del dato que se quiere obtener.</param>
        /// <returns>Devuelve el valor que contiene la clave en la sesión de la pagina.</returns>
        public static object ObtnerValorSesion(Page pagina, string clave)
        {

            return pagina.Session[clave];
        }
        /// <summary>
        /// Metodo que se encarga de obtener el "Type" de un tipo representado en cadena, el ensamblado o DLL que contiene el tipo de estar registrada en el GAC o 
        /// estar referenciada al proyecto.
        /// </summary>
        /// <param name="fullname">El nombre completo del tipo de dato.</param>
        /// <returns>Devuelve un objeto de tipo "Type" con los datos del tipo, devuelve NULL si el tipo no es encontrado.</returns>
        public static Type ObtenerTipoPorNombreEnsamblado(string fullname)
        {

            string dll = null;
            string ruta = fullname;
            try
            {
                if (fullname.Contains("-"))
                {
                    dll = fullname.Split('-')[0];
                    ruta = fullname.Split('-')[1];
                }
                else
                    dll = fullname.Split('.')[0];
                return Assembly.Load(dll).GetType(ruta);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Metodo que se encarga de convertir una cadena en numero.
        /// </summary>
        /// <param name="cadena">Cadena a convertir.</param>
        /// <returns>Devuelve el numero como System.Int32, si la cadena no es numero, devuelve 0.</returns>
        public static int Numero(object cadena)
        {
            try
            {
                if (cadena != null)
                    return int.Parse(cadena.ToString());
                else

                    return 0;
            }
            catch { return 0; }
        }


        /// <summary>
        /// Metodo generico que se encarga de convertir un valor a un tipo en especifico, no soporta los valores nullables, por ejemplo int?,bool?.
        /// </summary>
        /// <typeparam name="T">Tipo de dato al cual se quiere convertir el valor.</typeparam>
        /// <param name="dato">Dato a convertir.</param>
        /// <returns>Devuelve el valor convertido, si la conversión no se realiza, se devuelve el valor Default del tipo de dato.</returns>
        public static T Numero<T>(object dato)
        {
            try
            {
                if (dato == null || dato.ToString() == "")
                    return default(T);
                else
                    return (T)Convert.ChangeType(dato, typeof(T));
            }
            catch { return default(T); }
        }

        /// <summary>
        /// <summary>
        /// Metodo generico que se encarga de convertir un valor a un tipo en especifico, permitiendo al usuario indicar el valor por default que quiere que se devuelva
        /// si la conversión falla, no soporta los tipos nullables, por ejemplo int?,bool?.
        /// </summary>
        /// <typeparam name="T">Tipo de dato al cual se quiere convertir el valor.</typeparam>
        /// <param name="dato">Dato a convertir.</param>
        /// <param name="def">El valor por default, si la conversión falla.</param>
        /// <returns>Devuelve el valor convertido, si la conversión no se realiza, se devuelve el valor Default enviado por el usuario en el parametro "def".</returns>
        public static T Numero<T>(object dato, object def)
        {
            try
            {
                if (dato == null || dato.ToString() == "")
                    return (T)def;
                else
                    return (T)Convert.ChangeType(dato, typeof(T));
            }
            catch { return (T)def; }
        }

        /// <summary>
        /// Metodo que se encarga de obtener el valor por default de un tipo.
        /// </summary>
        /// <param name="tipo">El tipo del cual se quiere obtener el valor por default.</param>
        /// <returns>Devuelve el valor por default del tipo representado como "System.Object".</returns>
        public static object ObtenerDefaultTipo(Type tipo)
        {
            dynamic instancia = CrearInstanciaGenerico(typeof(DefaultTipo<>), tipo);
            return instancia.ObtenerValorDefault();

        }
        /// <summary>
        /// Metodo que se encarga de asignar un valor a una propiedad de un control web.
        /// </summary>
        /// <param name="control_">Control web, al cual se le asignará el valor.</param>
        /// <param name="propiedad">Nombre de la propiedad en la cual se quiere asignar el valor.</param>
        /// <param name="valor">El valor a escribir.</param>
        /// <param name="formatoValor">Indica el formato en el que se quiere presentar los datos en el control.</param>
        public static void SetValorControlWeb(Control control_, string propiedad, object valor, string formatoValor = null)
        {

            if (control_ is UpdatePanel)
            {
                foreach (Control ctrl in (control_ as UpdatePanel).ContentTemplateContainer.Controls)
                    SetValorControlWeb(ctrl, propiedad, valor);
            }
            else
            {
                if (propiedad == null)
                    return;
                PropertyInfo prop = control_.GetType().GetProperty(propiedad);

                if (prop != null)
                {
                    try
                    {

                        if (formatoValor == null)
                            prop.SetValue(control_, Convertir(valor, prop.PropertyType), null);
                        else
                        {
                            
                            string[] formatoConvertir = formatoValor.Split('~');
                            string[] formatoReal = null;
                            if (formatoConvertir.Length > 1)
                            {
                                formatoReal = formatoConvertir[1].Split('|');
                            }

                            prop.SetValue(control_, (valor as dynamic).ToString(formatoReal == null ? null : formatoReal[0]),null);
                        }
                    }
                    catch { }
                }
            }

        }



        /// <summary>
        /// Metodo que se encarga de obtener el valor de un control web enlazado a un campo dinamico, indicando el tipo de editor.
        /// </summary>
        /// <param name="control_">Control web del cual se obtiene los datos.</param>
        /// <param name="tipo">Tipo de editor, representado como entero, este valor debe estar en el enumerado "Enumerados.TIPO_EDITOR".</param>
        /// <returns>Devuelve el valor(System.Object) del control web de acuerdo al tipo de editor configurado.</returns>
        public static object GetValorControlWeb(Control control_, int tipo)
        {

            return GetValorControlWeb(control_, GetPropiedadValorEditor((Enumerados.TIPO_EDITOR)tipo));


        }


        /// <summary>
        /// Metodo que se encarga de obtener el valor de una propiedad de un control web.
        /// </summary>
        /// <param name="control_">Control web, al cual se le leerá el valor.</param>
        /// <param name="propValor">Nombre de la propiedad en la cual se quiere leer el valor.</param>        
        /// <returns>Devuelve el valor(System.Object) de la propiedad, si no se encuentra la propiedad, devuelve un valor NULL.</returns>
        public static object GetValorControlWeb(Control control_, string propValor)
        {
            PropertyInfo prop = control_.GetType().GetProperty(propValor);
            if (prop != null)
            {
                return prop.GetValue(control_, null);
            }
            else
                return "";

        }
        /// <summary>
        /// Metodo que se encarga de crear una instancia de un tipo, el ensamblado o DLL que contiene el tipo de estar registrada en el GAC o 
        /// estar referenciada al proyecto.
        /// </summary>
        /// <param name="tipo">Tipo del cual se quiere crear una nueva instancia.</param>
        /// <returns>Devuelve la instancia del tipo, devuelve null si no se logro encontrar el tipo.</returns>
        public static object CrearInstancia(Type tipo)
        {
            try
            {
                return Activator.CreateInstance(tipo);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Metodo que se encarga de crear una instancia de un tipo representado como cadena, el ensamblado o DLL que contiene el tipo de estar registrada en el GAC o 
        /// estar referenciada al proyecto.
        /// </summary>
        /// <param name="nombreCompleto">Nombre completo del tipo del cual se quiere crear una nueva instancia.</param>
        /// <returns>Devuelve la instancia del tipo, devuelve null si no se logro encontrar el tipo.</returns>
        public static object CrearInstancia(string nombreCompleto)
        {
            try
            {
                string[] sep = nombreCompleto.Split('.');
                return Activator.CreateInstance(sep[0], nombreCompleto).Unwrap();
            }
            catch { return null; }
        }
        /// <summary>
        /// Metodo que se encarga de crear una instancia de un tipo generico, el ensamblado o DLL que contiene el tipo de estar registrada en el GAC o 
        /// estar referenciada al proyecto.
        /// </summary>
        /// <param name="tipoGenerico">El tipo generico del cual se quiere crear una nueva instancia.</param>
        /// <param name="tipos">Los tipos de datos se envian como parametros para generar el tipo generico.</param>
        /// <returns>Devuelve la instancia del tipo, devuelve null si no se logro encontrar el tipo.</returns>
        public static object CrearInstanciaGenerico(Type tipoGenerico, params Type[] tipos)
        {
            try
            {
                Type ntipo = tipoGenerico.MakeGenericType(tipos);

                return Activator.CreateInstance(ntipo);
            }
            catch { return null; }
        }
        /// <summary>
        /// Metodo que se encarga de crear una instancia de un tipo representado como cadena, este metodo permite especificar el ensamblado en el cual se encuentra el tipo,
        /// para que la instancia se creé, el ensamblado debe estar en el GAC o en la carpeta BIN de la aplicación WEB.
        /// </summary>
        /// <param name="dll">Nombre completo del ensamblado o DLL que contiene el tipo, envié el valor nulo o la cadena "CONTROL" para cargar la DLL "System.web" .</param>
        /// <param name="tipo">Nombre completo del tipo del cual se quiere crear la nueva instancia.</param>
        /// <returns>Devuelve la instancia del tipo</returns>
        /// <exception cref="System.Exception">Excepcion que indica que el tipo no existe.</exception>
        public static object ObtenerTipo(string dll, string tipo)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(dll) || dll.ToUpper() == "CONTROL")
                    dll = typeof(System.Web.UI.Control).Assembly.FullName;
                var assem = Activator.CreateInstance(dll, tipo);
                return assem.Unwrap();

            }
            catch
            {
                throw new Exception(string.Format("No existe el tipo {1} en el ensamblado {0}, revise la configuración de la entidad.", dll, tipo));
            }
        }
        /// <summary>
        /// Metodo que se encarga de convertir un valor a un tipo en especifico, a diferencia de los metodos anteriores, este metodo soporta los tipos nullable por ejemplo
        /// el int?,bool?.
        /// </summary>
        /// <param name="dato">Dato a convertir.</param>
        /// <param name="tipo">El tipo de dato al cual se quiere convertir el valor.</param>
        /// <param name="vdef">El valor por default, si la conversión falla.</param>
        /// <returns>Devuelve el valor convertido, si la conversión no se realiza, se devuelve el valor Default enviado por el usuario en el parametro "def".</returns>
        public static object Convertir(object dato, Type tipo, object vdef = null)
        {
            if (dato == null || dato.Equals(DBNull.Value) || dato.ToString() == "")
                return ObtenerDefaultTipo(tipo);
            else
            {
                try
                {
                    if (tipo.IsGenericType && !tipo.IsEnum)
                    {

                        object res = CrearInstancia(tipo);

                        if (tipo.Name.ToUpper().Contains("NULLAB"))
                        {
                            res = Convert.ChangeType(dato, tipo.GetGenericArguments()[0]);
                        }
                        else
                        {

                            PropertyInfo prop = tipo.GetProperty("Value");
                            prop.SetValue(res, Convert.ChangeType(dato, tipo.GetGenericArguments()[0]), null);
                        }
                        return res;

                    }
                    else
                        return Convert.ChangeType(dato, tipo);
                }
                catch
                {

                    return ObtenerDefaultTipo(tipo);
                }
            }
        }

        /// <summary>
        /// Metodo que se encarga de obtener la propiedad que contiene el valor de un control web, de acuerdo al tipo de editor.
        /// </summary>
        /// <param name="editor">Tipo de editor.</param>
        /// <returns>Nombre de la propiedad del control web.</returns>
        public static string GetPropiedadValorEditor(Enumerados.TIPO_EDITOR editor)
        {

            switch (editor)
            {
                case Enumerados.TIPO_EDITOR.CHECK:
                    return "Checked";
                    break;
                case Enumerados.TIPO_EDITOR.LISTA:
                    return "SelectedValue";
                    break;
                case Enumerados.TIPO_EDITOR.HIDDEN:
                    return "Value";
                default:
                    return "Text";
                    break;
            }
        }
        /// <summary>
        /// Metodo que se encarga de verificar si un dato es de un tipo en especifico.
        /// </summary>
        /// <typeparam name="T">Tipo de dato usado para realizaar la validación.</typeparam>
        /// <param name="Valor">Valor a validar.</param>
        /// <returns>Valor que indica si se logro convertir el valor al tipo de dato.</returns>
        public static bool EsDeTipo<T>(object Valor)
        {
            try
            {
                Convert.ChangeType(Valor, typeof(T));
                return true;

            }
            catch { return false; }
        }


        /// <summary>
        /// Metodo generico que se encarga de convertir un valor a un tipo en especifico, a diferencia de los metodos anteriores, este metodo soporta los tipos nullable por ejemplo
        /// el int?,bool?.
        /// </summary>
        /// <typeparam name="T">El tipo de dato al cual se quiere convertir el valor</typeparam>
        /// <param name="Valor">Valor a convertir.</param>
        /// <returns>Devuelve el valor convertido, si la conversión no se realiza, se devuelve el valor Default del tipo.</returns>
        public static T Convertir<T>(object Valor)
        {
            if (Valor == null || Valor.Equals(DBNull.Value) || Valor.ToString() == "")
                return default(T);
            else
            {
                try
                {
                    if (typeof(T).IsGenericType)
                    {

                        T res = Activator.CreateInstance<T>();

                        if (typeof(T).Name.ToUpper().Contains("NULLAB"))
                        {
                            res = (T)Convert.ChangeType(Valor, typeof(T).GetGenericArguments()[0]);
                        }
                        else
                        {

                            PropertyInfo prop = typeof(T).GetProperty("Value");
                            prop.SetValue(res, Convert.ChangeType(Valor, typeof(T).GetGenericArguments()[0]), null);
                        }
                        return res;

                    }
                    else
                        return (T)Convert.ChangeType(Valor, typeof(T));
                }
                catch
                {

                    return default(T);
                }
            }
        }

    }
}
